package com.erp.service.util;

import http.IHTTPListener;
import http.raw.HttpURLConnectionClient;
import http.raw.HttpUrlConnectionResponseInfo;
import http.HTTPException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import com.erp.service.util.net.IResponseInfo;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

public class IOHelper {
	
	/**
	 * 文件大小
	 */
	private final static int FILESIZE = 4 * 1024;
	
	private final static String TAG = IOHelper.class.getSimpleName();
	
	/**
	 * 判断SD卡是否存在
	 */
	public static boolean isSdCardExist() {
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
			return true;
		else 
			return false;
	}
	
	/**
	 * 返回SD卡跟目录
	 */
	public static String getSdCardPath() {
		File sdDir = null;
		//判断SD卡是否存在
		boolean sdCardExist = isSdCardExist(); 
		if (sdCardExist) {
			//获取跟目录
			sdDir = Environment.getExternalStorageDirectory();
			return sdDir.toString();
		}
		else 
			return null;
	}
	
	/**
	 * 判断路径是否存在
	 * 
	 * @param path
	 * @return
	 */
	public static boolean isExistByPath(String path) {
		File file = new File(path);
		return file.exists();
	}
	
	/**
	 * 创建文件夹
	 * 
	 * @param path
	 * @return
	 */
	public static File createDir(String path) {
		File file = new File(path);
		if (!file.exists())
			file.mkdirs();
		return file;
	}
	
	/**
	 * 创建指定文件
	 * 如果父目录不存在也会创建
	 * @param f
	 */
	public static void createFile(File f){
		if (!f.exists()) {
			if (!f.getParentFile().exists()) {
				f.getParentFile().mkdirs();
			}
			
			try {
				f.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}	
	
	/**
	 * 流拷贝
	 * 从in中拷贝数据到out中
	 * @param in
	 * @param out
	 * @throws IOException
	 */
	public static void copy(InputStream in, OutputStream out) throws IOException {
		byte[] buffer = new byte[2048];
		int length = 0;
		while ((length = in.read(buffer)) > 0) {
			out.write(buffer, 0, length);
		}
		out.flush();
		in.close();
		out.close();
	}
	
	/**
	 * 获取职员头像
	 * @param url 头像网络地址
	 * @param path 保存的本地路径
	 * @param listener 回调函数（执行在主线程）
	 */
	public static void getPeoPhoto(String url, String path, final IHTTPListener<IResponseInfo> listener) {
		final String p = path;
		
		HttpURLConnectionClient client = new HttpURLConnectionClient();
		client.setFullUrl(url);
		client.setConnectTimeout(3000);
		client.setReadTimeout(5000);
		
		client.sendAsync(new IHTTPListener<IResponseInfo>() {			
			@Override
			public void onSuccess(Object req, IResponseInfo result) {
				InputStream in;
				HttpUrlConnectionResponseInfo res = (HttpUrlConnectionResponseInfo) result;
				
				try {					
					int resCode = res.getHttpURLConnection().getResponseCode();
					if (resCode == HttpURLConnection.HTTP_OK) {
						in = res.getHttpURLConnection().getInputStream();
						File f = new File(p);
						createFile(f);
						FileOutputStream out = new FileOutputStream(f);
						
						copy(in, out);
						if (listener != null)
							listener.onSuccess(req, result);
					}
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					if (res.getHttpURLConnection() != null)
						res.getHttpURLConnection().disconnect();
				}
			}
			
			@Override
			public void onException(Object req, HTTPException e) {
				if (listener != null)
					listener.onException(req, e);				
			}
		});		
	}


	/**
	 * 将请求参数是name1=value1&name2=value2的形式的字符串转为键值对
	 *
	 * @param paramsString
	 *            {@link String} name1=value1&name2=value2形式的请求参数
	 * @return
	 */
	public static List<NameValuePair> toNameValuePairList(String paramsString) {
		List<NameValuePair> NameValuePairList = new ArrayList<NameValuePair>();
		if (paramsString != null && !paramsString.equals("")) {
			String[] paramsArray = paramsString.split("\\&");
			for (String param : paramsArray) {
				String[] keyValue = param.split("\\=");
				NameValuePairList.add(new BasicNameValuePair(keyValue[0],
						keyValue.length > 1 ? keyValue[1] : ""));
			}
		}
		return NameValuePairList;
	}

	/**
	 * 将键值对转化为name1=value1&name2=value2形式的字符串
	 *
	 * @param params
	 *            {@link List} 键值对
	 * @return
	 */
	public static String fromNameValuePairList(List<NameValuePair> params) {
		String result = "";

		for (NameValuePair nameValuePair : params) {
			result += nameValuePair.getName() + "=" + nameValuePair.getValue()
					+ "&";
		}
		if (result.endsWith("&"))
			result = result.substring(0, result.length() - 1);
		return result;
	}
	
	/**
	 * 将字节数组转为十六进制
	 * 
	 * @param data
	 *            {@link byte[]} 字节数组
	 * @return
	 */
	private static String convertToHex(byte[] data) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < data.length; i++) {
			int halfbyte = (data[i] >>> 4) & 0x0F;
			int two_halfs = 0;

			do {
				if ((0 <= halfbyte) && (halfbyte <= 9))
					buf.append((char) ('0' + halfbyte));
				else
					buf.append((char) ('a' + (halfbyte - 10)));
				halfbyte = data[i] & 0x0F;
			} while (two_halfs++ < 1);
		}

		return buf.toString();
	}

	/**
	 * 获取文件SHA1散列
	 * 
	 * @param path
	 *            {@link String} 文件路径
	 */
	public static String getFileSha1(String path) throws OutOfMemoryError,
			IOException {
		File file = new File(path);
		return getFileSha1(file);
	}
	

	/**
	 * 获取文件SHA1散列
	 * 
	 * @param file
	 *            {@link File} 文件对象
	 */
	public static String getFileSha1(File file) throws OutOfMemoryError,
			IOException {

		FileInputStream in = new FileInputStream(file);
		MessageDigest messagedigest;

		try {
			messagedigest = MessageDigest.getInstance("SHA-1");

			byte[] buffer = new byte[1024 * 10];
			int len = 0;

			while ((len = in.read(buffer)) > 0) {
				// 该对象通过使用 update（）方法处理数据
				messagedigest.update(buffer, 0, len);
			}

			// 对于给定数量的更新数据，digest 方法只能被调用一次。在调用 digest 之后，MessageDigest
			// 对象被重新设置成其初始状态。
			return convertToHex(messagedigest.digest());
		} catch (NoSuchAlgorithmException e) {
			Log.e(TAG, "[getFileSha1]:" + e.getStackTrace().toString());
			e.printStackTrace();
		} catch (OutOfMemoryError e) {
			Log.e(TAG, "[getFileSha1]:" + e.getStackTrace().toString());
			e.printStackTrace();
			throw e;
		} finally {
			in.close();
		}

		return null;
	}
	
	/**
	 * 获取文件MD5散列
	 * 
	 * @author lik
	 * 
	 * @param path
	 *            {@link String} 文件路径
	 */
	public static String getFileMD5(String path) throws OutOfMemoryError,
			IOException {
		File file = new File(path);
		return getFileSha1(file);
	}
	
	/**
	 * 获取文件SHA1散列
	 * 
	 * @author lik
	 * 
	 * @param file
	 *            {@link File} 文件对象
	 */
	public static String getFileMD5(File file) throws OutOfMemoryError,
			IOException {

		FileInputStream in = new FileInputStream(file);
		MessageDigest messagedigest;

		try {
			messagedigest = MessageDigest.getInstance("MD5");

			byte[] buffer = new byte[1024 * 10];
			int len = 0;

			while ((len = in.read(buffer)) > 0) {
				// 该对象通过使用 update（）方法处理数据
				messagedigest.update(buffer, 0, len);
			}

			// 对于给定数量的更新数据，digest 方法只能被调用一次。在调用 digest 之后，MessageDigest
			// 对象被重新设置成其初始状态。
			return convertToHex(messagedigest.digest());
		} catch (NoSuchAlgorithmException e) {
			Log.e(TAG, "[getFileMD5]:" + e.getStackTrace().toString());
			e.printStackTrace();
		} catch (OutOfMemoryError e) {
			Log.e(TAG, "[getFileMD5]:" + e.getStackTrace().toString());
			e.printStackTrace();
			throw e;
		} finally {
			in.close();
		}

		return null;
	}
	
	/**
	 * 截取文件开头
	 * 
	 * @param fileFullName
	 *            {@link String} 路径文件名
	 * @param input
	 *            {@link InputStream} 输入流
	 * @param totalSize
	 *            {@link Long} 輸入流的大小
	 * @param startPos
	 *            {@link Long} 開始的位置
	 * @return
	 * @throws IOException
	 */
	public static File trancStart(String fileFullName, InputStream input,
			long totalSize, long startPos) throws IOException {

		File file = new File(fileFullName);
		file.delete();
		file = new File(fileFullName);
		file.createNewFile();
		input.skip(startPos);
		return writeFromInput(file, input, totalSize, 0, null);
	}

	/**
	 * 将一个InputStream里面的数据写入文件
	 * 
	 * @param file
	 *            {@link File} 文件
	 * @param input
	 *            {@link InputStream} 输入流
	 * @param totalSize
	 *            {@link Long} 輸入流的大小（用于进度条使用）
	 * @param startPos
	 *            {@link Long} 開始的位置（ 用於进度条使用）
	 * @return File
	 */
	private static File writeFromInput(File file, InputStream input,
			long totalSize, long startPos, DownloadProgressListener listener) {
		RandomAccessFile fos = null;

		try {
			fos = new RandomAccessFile(file, "rw");
			fos.seek(startPos);
			long downloadSize = startPos;
			byte[] buffer = new byte[FILESIZE];
			int count = 0;
			while ((count = input.read(buffer, 0, FILESIZE - 1)) > 0) {
				fos.write(buffer, 0, count);
				downloadSize += count;
				if (listener != null)
					listener.transferred(count, downloadSize, totalSize);
			}

		} catch (Exception e) {
			Log.e(TAG, "[writeFromInput]:" + e.getStackTrace().toString());
			e.printStackTrace();
		} finally {
			try {
				fos.close();
			} catch (IOException e) {
				Log.e(TAG, "[writeFromInput]:" + e.getStackTrace().toString());
				e.printStackTrace();
			}
		}

		return file;
	}

	/**
	 * 将一个InputStream里面的数据写入指定路径
	 * 
	 * @param path
	 *            {@link String} 路径（不包含文件名）
	 * @param fileName
	 *            {@link String} 文件名
	 * @param input
	 *            {@link InputStream} 输入流
	 * @param totalSize
	 *            {@link Long} 輸入流的大小（用于进度条使用）
	 * @param startPos
	 *            {@link Long} 開始的位置（ 用於进度条使用）
	 * @return File
	 */
	public static File writeFromInput(String path, String fileName,
			InputStream input, long totalSize, long startPos,
			DownloadProgressListener listener) {
		File file = null;
		if (startPos == 0) {
			file = new File(path, fileName);
			IOHelper.createFile(file);
		} else {
			file = new File(path, fileName);
		}
		return writeFromInput(file, input, totalSize, startPos, listener);
	}

	/**
	 * 覆盖写入字符串到文件,如果文件已存在会删除原有文件
	 * 
	 * @param FileFullName
	 *            {@link String} 路径文件名
	 * @param text
	 *            {@link String} 写入的数据
	 * @return
	 */
	public static boolean writeStringToFile(String FileFullName, String text) {
		FileOutputStream os = null;

		try {
			File file = new File(FileFullName);
			if (file.exists()) {
				file.delete();
			}
			file.createNewFile();

			os = new FileOutputStream(file);
			os.write(text.getBytes());
			os.flush();
			return true;

		} catch (IOException e) {
			Log.e(TAG, "[writeStringToFile]:" + e.getStackTrace().toString());
			e.printStackTrace();
			return false;

		} finally {
			try {
				if (os != null)
					os.close();
			} catch (IOException e) {
				// do nothing
			}
		}
	}

	/**
	 * 读取文件为字符串
	 * 
	 * @param path
	 *            {@link String} 文件路径
	 * @return String 读取文件完成后返回的字符串
	 * 
	 */
	public static String readStringFromFile(String path) {
		FileReader file = null;
		BufferedReader buf = null;

		try {
			file = new FileReader(path);
			buf = new BufferedReader(file);
			return buf.readLine();

		} catch (Exception e) {
            e.printStackTrace();
			return null;
		} finally {
			try {
				file.close();
			} catch (Exception e) {
				Log.e(TAG, "[readStringFromFile]:"
						+ e.getStackTrace().toString());
				e.printStackTrace();
			}
		}
	}
	

    public static String getRealPathFromURI(final Context context, final Uri contentUri) {
        // get path from uri like content://media//
        final Cursor cursor = context.getContentResolver().query(contentUri,
                new String[] { MediaColumns.DATA }, null, null, null);
        String path = null;
        if (cursor != null) {
            final int column_index = cursor
                    .getColumnIndexOrThrow(MediaColumns.DATA);
            cursor.moveToFirst();
            path = cursor.getString(column_index);
        } else {
            path = null;
        }
        cursor.close();
        if (path == null) {
            path = contentUri.getPath();
        }
        return path;
    }
}
